part of 'component.dart';

class DashBorder extends StatelessWidget {
  const DashBorder({
    Key? key,
    required this.child,
    this.borderWidth = 1,
    this.length = 5,
    this.color = Colors.black,
    this.margin = EdgeInsets.zero,
  }) : super(key: key);
  final Widget child;
  final double borderWidth;
  final double length;
  final Color color;
  final EdgeInsets margin;
  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: margin,
      child: Stack(
        children: [
          Positioned.fill(
            child: CustomPaint(
              painter: DashBorderPainter(
                borderWidth: borderWidth,
                length: length,
                color: color,
              ),
            ),
          ),
          child,
        ],
      ),
    );
  }
}

class DashBorderPainter extends CustomPainter {
  DashBorderPainter({
    this.borderWidth = 1,
    this.length = 5,
    this.color = Colors.black,
  });

  final double borderWidth;
  final double length;
  final Color color;
  @override
  void paint(Canvas canvas, Size size) {
    var ns = Size(size.width - borderWidth / 2, size.height - borderWidth / 2);
    var path = Path();
    draw(path, size.width, borderWidth / 2, fromLeft: true, fromTop: true);
    draw(path, size.height, ns.width, fromLeft: false, fromTop: true);
    draw(path, size.width, ns.height, fromLeft: true, fromTop: false);
    draw(path, size.height, borderWidth / 2, fromLeft: false, fromTop: false);
    path.close();
    canvas.drawPath(
      path,
      Paint()
        ..strokeWidth = borderWidth
        ..color = color
        ..style = PaintingStyle.stroke,
    );
  }

  void draw(
    Path path,
    double total,
    double diff, {
    bool fromTop = true,
    bool fromLeft = true,
  }) {
    var space = length - 1;

    var n = (total / (length + space)).floor();
    var x1 = length / 2;
    var p1 = _point(0, diff, fromLeft: fromLeft, fromTop: fromTop);
    path.moveTo(p1.dx, p1.dy);
    var p2 = _point(x1, diff, fromLeft: fromLeft, fromTop: fromTop);
    path.lineTo(p2.dx, p2.dy);

    var i = 0;
    while (i < n) {
      x1 += space;
      var p1 = _point(x1, diff, fromLeft: fromLeft, fromTop: fromTop);
      path.moveTo(p1.dx, p1.dy);
      x1 += length;
      if (i == n - 1) {
        x1 = total;
      }
      var p2 = _point(x1, diff, fromLeft: fromLeft, fromTop: fromTop);
      path.lineTo(p2.dx, p2.dy);

      i++;
    }
  }

  Offset _point(
    double p,
    double total, {
    bool fromTop = true,
    bool fromLeft = true,
  }) {
    if (fromLeft && fromTop) {
      return Offset(p, 0);
    }
    if (!fromLeft && fromTop) {
      return Offset(total, p);
    }
    if (fromLeft && !fromTop) {
      return Offset(p, total);
    }
    return Offset(0, p);
  }

  @override
  bool shouldRepaint(DashBorderPainter oldDelegate) => false;

  @override
  bool shouldRebuildSemantics(DashBorderPainter oldDelegate) => false;
}
